<?php

class CDb extends CBase {
	
	private static $instance = null;
	
	public $conn	= null;
	
	public $version = null;

	public $lastId	= null;

	public $error	= null;

	public $errno	= null;

	public $query	= null;

	public $sql		= null;

	private function __construct() {
		
	}

	public static function getInstance($options = array()) {
		self::$instance = null;
		if(!self::$instance) {
			switch($options["driver"]) {
				case "pdo":
					self::$instance = new CDb_pdo($options);
					break;
				case "mssql":
					self::$instance = new CDb_mssql($options);
					break;
				case "mysql":
				default:
					self::$instance = new CDb_mysql($options);
					break;
			}
		}
		return self::$instance;
	}
	
	public function select($options = array(),$type = 'rows',$keyid = '') {
		$sql = $this->parseSelect($options);
		return $this->execute($sql) ? $this->getResults($type,$keyid) : false;
	}
	
	public function insertMulti($dataList,$options = array(),$replace = false) {
		return false;
	}
	
	public function parseFields($fields) {
		if(!$fields || $fields == '*') return '*';
		
		if(is_string($fields)) {
			$fields = explode(",",$fields);
		}
		if(is_array($fields)) {
			$array = array();
			$pre   = '';
			foreach($fields as $key => $field) {
				if(is_string($field)) {//如果为字符串
					if(strpos($field,".")) {
						$field = explode(".",$field);
						$pre   = $field[0] . ".";
						$field = $field[1];
					}
					if(strpos($field,"|")) {//支持field1|field2形式
						$field = explode("|",$field);
						$array[] = $pre . $this->quoteKey($field[0]) . ' AS ' . $this->quoteKey($field[1]);
					} else {//普通的形式
						$array[] = $pre . $this->quoteKey($field);
					}
				}
			}
			return implode(',',$array);
		} 
		return '*';
	}

	public function parseSelect($options) {
		$sql = "SELECT "
			 . (!isset($options['distinct'])   ?  ''  : $this->parseDistinct($options['distinct']))
			 . (empty($options['fields'])      ?  '*' : $this->parseFields($options['fields']))
			 . $this->parseFrom($options['table'])
			 . (empty($options['join'])		   ?  ''  : $this->parseJoin($options['join']))
		     . (empty($options['where'])	   ?  ''  : $this->parseWhere($options['where']))
			 . (empty($options['group'])	   ?  ''  : $this->parseGroup($options['group']))
			 . (empty($options['having'])	   ?  ''  : $this->parseHaving($options['having']))
			 . (empty($options['order'])	   ?  ''  : $this->parseOrder($options['order']))
			 . (empty($options['limit'])	   ?  ''  : $this->parseLimit($options['limit']))
			 ;
		return $sql;
	}
	

	public function insert($data,$options = array(),$replace = false) {
		$values = $fields = array();
		foreach($data as $key => $value) {
			if(is_scalar($value)) {//过滤非标量数据
				$fields[] = $this->quoteKey($key);
				$values[] = $this->quoteValue($value);
			}
		}
		$sql = ($replace ? "REPLACE INTO " : "INSERT INTO ")
		     . $this->quoteKey($options['table'])
			 . cimplode($fields)
			 . ' VALUES '
			 . cimplode($values);

		return $this->execute($sql) ? $this->getLastId() : false;
	}
	
	public function update($data,$options = array()){
		$sql = "UPDATE "
		     . $this->quoteKey($options['table']) 
			 . $this->parseSet($data)
			 . $this->parseWhere(empty($options['where']) ?  '' : $options['where'])
			 . $this->parseLimit(empty($options['limit']) ?  '' : $options['limit'])
			 ;
		return $this->execute($sql) ? $this->getAffectedRows() : false;
	}
	
	//删除元素
	public function delete($options = array()) {
		$sql = "DELETE FROM "
		     . $this->quoteKey($options['table'])
			 . $this->parseWhere(empty($options['where']) ? '' : $options['where'])
			 . $this->parseLimit(empty($options['limit']) ? '' : $options['limit'])
			 ;
		return $this->execute($sql) ? $this->getAffectedRows() : false;
	}

	//解析set，用于update
	public function parseSet($data) {
		$sets = array();
		foreach($data as $key => $val) {
			$set	= $this->quoteKey($key);
			if(preg_match("/^(\+|-) ([0-9]+)$/",$val,$matches)) {//如果增加，减少
				$set .= '='.$this->quoteKey($key) . ' ' . $matches[1] . ' '.intval($matches[2]);
			} else if($val === "!".$key) {//如果是bool,ispublish=!ispublish
				$set .= '= IF('.$this->quoteKey($key).',0,1)';
			} else {//普通的值
				$set .= '='.$this->quoteValue($val);
			}
			$sets[] = $set;
		}
		return ' SET ' . implode(',',$sets);
	}
	
	//解析limit
	public function parseLimit($limit) {
		if(!$limit) return '';
		$limitstr = '';
		if(is_array($limit) && count($limit) == 2 ) {
			$limitstr = "{$limit[0]},{$limit[1]}";
		} else {
			$limitstr = "$limit";
		}
		return " LIMIT " . $limitstr;
	}
	
	public function parseFrom($from) {
		return ' FROM '.$from;
	}

	public function parseDistinct($distinct) {
		return isset($distinct) ?  ' DISTINCT ' : ''; 
	}
	
	public function parseOrder($orders) {
		$orderstr = '';
		if(!$orders) return '';
		if(is_string($orders)) {
			$orders = explode(",",$orders);
		}
		if(is_array($orders)) {
			$array = array();
			foreach($orders as $order) {
				$temp = explode(' ',$order);
				if(strpos($temp[0],".")) {
					list($pre,$key) = explode(".",$temp[0]);
					$array[] = $pre . '.' . $this->quoteKey($key) . (isset($temp[1]) ?  ' ' . $temp[1] : '');
				} else {
					$array[] = $this->quoteKey($temp[0]) . (isset($temp[1]) ?  ' ' . $temp[1] : '');
				}
			}
			$orderstr = implode(',',$array);
		}
		return ' ORDER BY '.$orderstr;
	}

	public function parseGroup($groups) {
		$groupstr = '';
		if(!$groups) return '';

		if(is_string($groups)) {
			$groups = explode(",",$groups);
		}
		
		$groupstr = '';
		if(is_array($groups)) {
			$array = array();
			foreach($groups as $key => $group) {
				$array[] = $this->quoteKey($group);
			}
			$groupstr = implode(",",$array);
		} 
		return ' GROUP BY ' . $groupstr;
	}
	
	//解析join
	public function parseJoin($join) {
		if(is_string($join)) return $join;//如果是字符串，直接返回
		
		if(!is_array($join) || empty($join['table']) || empty($join['on'])) return false;//join条件不合法

		$type  = empty($join['type']) ? "INNER" : strtoupper($join['type']);//join的方式，
		if(!in_array($type,array("INNER","RIGHT","LEFT")))  return false;//join方式不合法

		$on    = $join['on'];
		$onstr = '';
		if(preg_match("/^.+(=|,).+$/",$on,$matches)) {//形如a.catid=b.id,catid,id
			$deli	= $matches[1];
			list($afield,$bfield)	= explode($deli,$on);
			if(strpos($afield,".")) {
				list($pre,$afield) = explode(".",$afield);
				$afield = $pre . "." . $this->quoteKey($afield);
			} else {
				$afield = $this->quoteKey($afield);
			}
			if(strpos($bfield,".")) {
				list($pre,$bfield) = explode(".",$bfield);
				$bfield = $pre . "." . $this->quoteKey($bfield);
			} else {
				$bfield = $this->quoteKey($bfield);
			}
			$onstr =  " ON $afield = $bfield";
		} else {//形如uid
			$field = $this->quoteKey($on);
			$onstr = " ON a.$field = b.$field";
		}

		$table   = strtolower($join['table']);//join的表名
		
		$joinstr = " $type JOIN "
				 . $table
				 . $onstr ;
		return $joinstr;
	}

	public function parseHaving($having) {
		return $having ? ' HAVING '.$having : '';
	}

	//解析where
	public function parseWhere($where) {
		$wherestr = '';
		if(is_string($where)) {
			$wherestr = $where;
		} else if(is_array($where)){
			$logic = ' AND ';
			if(isset($where['_logic'])) {
				$logic = strtoupper($where['_logic']);
				($logic == 'OR') && ($logic = ' OR ') || ($logic = ' AND ');
				unset($where['_logic']);
			}
			foreach($where as $key => $val) {
				if( is_array($val)) {//如果是数组，递归处理，用key后面的|，&判断数组内部的conn
					$temp	    = "(" . trim($this->parseWhere($val),' WHERE ') . ")";
					$wherestr  .= $temp
							   . $logic
							   ;
				}  else if(is_scalar($val)) {
					$wherestr .=  $this->_parseWhere($key,$val) 
							  . $logic
							  ;
				}
			}
			$wherestr = trim($wherestr,$logic);
		}
		return empty($wherestr) ? $wherestr : ' WHERE ' . $wherestr;
	}

	//解析where子串
	public function _parseWhere($key,$val) {
		if(strpos($key,".")) {
			list($pre,$key) = explode(".",$key);
			$wherestr = "(" . $pre . "." . $this->quoteKey($key);
		} else {
			$wherestr = "(" . $this->quoteKey($key);
		}
		if(preg_match("/^(IN|NOT IN) ?\(?(.+?)\)?$/i",$val,$matches)) {
			$value = $this->quoteValue(explode(",",$matches[2]));
			$wherestr .= ' '.$matches[1]
				      .  ' '.cimplode($value)
					  ;
		} else if(preg_match("/^(>=|<=|>|<|LIKE|NOT LIKE|BETWEEN) ?(.+)$/i",$val,$matches)) {
			$wherestr .= ' ' .$matches[1]
					  .  ' ' .$matches[2]
					  ;
		} else {
			$wherestr .=  " = " . $this->quoteValue($val)
					  ;
		}
		$wherestr .= ")";
		return $wherestr;
	}

	//返回执行的错误
	public function getError() {
		return $this->error;
	}

	public function quoteKey($key) {
		return $key;
	}

	public function quoteValue($value) {
		return $value;
	}
	
	public function getLastId() {
		return $this->lastId;
	}

	public function sql() {
		return $this->sql;
	}
}